/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 **************************************************************************
 * MIFSS  - content storage system
 * 
 *
 * @uthors: uros.kristan@gmail.com (Uroš Kristan ) Urosk.NET
 *         jernej.svigelj@gmail.com (Jernej Švigelj) 
 */
package net.monare.mifss.workers.converters;

import net.monare.mifss.configurations.pojo.Property;
import net.monare.mifss.configurations.pojo.StorageDef;
import net.monare.mifss.exceptions.MediaConverterException;
import net.monare.mifss.workers.BaseTransformationHandler;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.SystemUtils;
import org.apache.log4j.Logger;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

abstract public class BaseMediaConverter {

    public static Logger logger = Logger.getLogger(BaseMediaConverter.class);

    private String converterBinFolder;

    private String converterExecutable;

    private File inputFile;

    private String inputMimeType;

    public StorageDef getStorageDef() {
        return storageDef;
    }

    public void setStorageDef(StorageDef storageDef) {
        this.storageDef = storageDef;
    }

    private File outputFile;

    private Map<String, Object> properties;

    private StorageDef storageDef;
    private List<String> supportedMimeTypes = new ArrayList<String>();

    abstract public String convert() throws MediaConverterException;

    private BaseTransformationHandler baseTransformationHandler;

    public BaseTransformationHandler getBaseTransformationHandler() {
        return baseTransformationHandler;
    }

    public void setBaseTransformationHandler(BaseTransformationHandler baseTransformationHandler) {
        this.baseTransformationHandler = baseTransformationHandler;
    }

    public boolean exec(String[] command) {

        Process proc;

        logger.debug("cmd: " + StringUtils.join(command, " "));
        try {

            proc = Runtime.getRuntime().exec(command);

            logger.debug("proc.std.error:" + IOUtils.toString(proc.getErrorStream(), "UTF-8"));
            logger.debug("proc.std.out:" + IOUtils.toString(proc.getInputStream(), "UTF-8"));

            //proc.destroy();

        } catch (IOException e) {
            System.out.println("IOException while trying to execute " + command);
            logger.error("IOException while trying to execute " + command, e);
            return false;
        }

        int exitStatus;

        while (true) {
            try {
                exitStatus = proc.waitFor();
                break;
            } catch (java.lang.InterruptedException e) {
                logger.error("Interrupted: Ignoring and waiting", e);
            }
        }
        if (exitStatus != 0) {
            logger.error("Error executing command: " + exitStatus);
        }

        return (exitStatus == 0);
    }

    public String getConverterBinFolder() {
        return converterBinFolder;
    }

    public String getConverterExecutable() {
        return converterExecutable;
    }

    public String getInputMimeType() {
        return inputMimeType;
    }




    public String getPropertyString(String key) throws MediaConverterException {


        // storage property overides
        for(Property p : getStorageDef().getProperties()){

            if(key.equals(p.getName())) return (String)p.getValue();
        }

        if (properties!=null && properties.containsKey(key)) {
            return (String) properties.get(key);
        }else {
            logger.warn("No property key: " +key);
            return null;

        }
    }

    public List<String> getSupportedMimeTypes() {

        return supportedMimeTypes;

    }

    public void setConverterBinFolder(String converterBinFolder) {
        this.converterBinFolder = converterBinFolder;
    }

    public void setConverterExecutable(String converterExecutable) {
        this.converterExecutable = converterExecutable;
    }

    public File getInputFile() {
        return inputFile;
    }

    public void setInputFile(File inputFile) {
        this.inputFile = inputFile;
    }

    public File getOutputFile() {
        return outputFile;
    }

    public void setOutputFile(File outputFile) {
        this.outputFile = outputFile;
    }

    public void setInputMimeType(String inputMimeType) {
        this.inputMimeType = inputMimeType;
    }

    public void setProperties(Map<String, Object> properties) {
        this.properties = properties;
    }

    public void setSupportedMimeTypes(List<String> supportedMimeTypes) {
        this.supportedMimeTypes = supportedMimeTypes;
    }


    public String getOsAwarePath(String path) throws MediaConverterException {

        if(SystemUtils.IS_OS_LINUX){
            return path;
        } else if (SystemUtils.IS_OS_WINDOWS){
            return ("\"" + path+ "\"");

        } else {
            throw new MediaConverterException("OS platform not supported ...");
        }
    }



}
